<?php

namespace app\api\controller;

use app\admin\model\member\Payorder;
use app\api\model\BaseModel;
use app\api\model\ConfigModel;
use app\api\model\GoodsModel;
use app\api\model\HomeOrderModel;
use app\api\model\RecycleOrderItemModel;
use app\api\model\RecycleOrderModel;
use app\api\model\UserModel;
use app\api\model\UserWxLogModel;
use app\common\controller\Api;
use think\Db;
use think\response\Json;
use wx\Util;
use wx\WxMessage;

class Wxpay extends Api
{
    protected $noNeedLogin = ['notify', 'recycleNotify'];
    protected $noNeedRight = ['*'];

    public function _initialize()
    {
        parent::_initialize();
    }

    /**
     * 微信支付回调
     */
    public function notify()
    {
        $file = 'wx_notify';
        $testxml = file_get_contents("php://input");
        BaseModel::log($file, $testxml);
        $jsonxml = json_encode(simplexml_load_string($testxml, 'SimpleXMLElement', LIBXML_NOCDATA));
        $result = json_decode($jsonxml, true);//转成数组，
        if ($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS') {
            //获取订单
            $order = Payorder::where('no', $result['out_trade_no'])->where('status', 0)->find();
            //修改订单
            if ($order) {
                //变更订单状态
                Db::startTrans();
                try {
                    $order->status = 1;
                    $order->paid_time = time();
                    $order->payment_no = $result['transaction_id'];
                    if (!$order->save()) {
                        throw new \Exception("保存订单状态失败");
                    }
                    //修改用户
                    $userModel = new UserModel();
                    $result = $userModel->incrementScore($order['user_id'], $order->num);
                    if (!$result) {
                        throw new \Exception("修改用户记录失败");
                    }
                    Db::commit();
//                    //增加下单订阅消息提醒
//                    $user = UserModel::getUser($order['user_id']);
//                    $wx = new WxMessage();
//                    $data = $wx->createOrderMessage($user['openid'], $order);
//                    $wx->send_template_message($data);
                    echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
                    exit('succeed');
                } catch (\Exception $e) {
                    Db::rollback();
                    BaseModel::log($file, $e->getMessage());
                    echo '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>';
                    exit('error');
                }
            } else {
                echo '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>';
                exit('error');
            }
        } else {
            echo '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>';
            exit('error');
        }
    }

    /**
     * 回收-微信支付回调
     */
    public function recycleNotify()
    {
        $file = 'wx_recycle_notify';
        $testxml = file_get_contents("php://input");
        BaseModel::log($file, $testxml);
        $jsonxml = json_encode(simplexml_load_string($testxml, 'SimpleXMLElement', LIBXML_NOCDATA));
        $result = json_decode($jsonxml, true);//转成数组，
        if ($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS') {
            $money = bcdiv($result['total_fee'], 100, 2);
            //获取订单
            $order = RecycleOrderModel::where('no', $result['out_trade_no'])->where('status', RecycleOrderModel::STATUS_ORDER_RECEIVED)->find();
            //修改订单
            if ($order) {
                //变更订单状态
                Db::startTrans();
                try {
                    //更新用户的订单状态
                    $order->complete_time = time();
                    $order->status = RecycleOrderModel::STATUS_COMPLETED;
                    $order->actual_price = $money;
                    $order->pay_type = RecycleOrderModel::PAY_TYPE_PLATFORM;
                    if (!$order->save()) {
                        throw new \Exception('更新订单信息失败');
                    }
                    $category_name = RecycleOrderItemModel::categoryName($order->id);
                    //增加用户的余额，财务记录
                    UserModel::money($order->user_id, $money, $category_name);
                    //如果存在上级，并且是用户的首单，增加上级的红包记录
                    $saleUser = UserModel::where('id', $order->user_id)->find();
                    if ($saleUser['pid']) {
                        $order_count = RecycleOrderModel::where('user_id', $order['user_id'])->where('status', RecycleOrderModel::STATUS_COMPLETED)->find();
                        if (!$order_count) {
                            $redbag = ConfigModel::getValue('invitation_user_money', 'basic');
                            $memo = "下级用户{$saleUser['nickname']}下单奖励";
                            UserModel::redbag($saleUser['pid'], $redbag, '邀好友', $memo);
                        }
                    }
                    $data = [
                        'type' => UserWxLogModel::TYPE_RECYCLE,
                        'user_id' => $order['role_id'],
                        'money' => $money,
                        'status' => UserWxLogModel::STATUS_DEC,
                        'memo' => $category_name,
                        'createtime' => time()
                    ];
                    if (!UserWxLogModel::create($data)) {
                        throw new \Exception("增加微信记录失败");
                    }
                    Db::commit();
                    echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
                    exit('succeed');
                } catch (\Exception $e) {
                    Db::rollback();
                    BaseModel::log($file, $e->getMessage());
                    echo '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>';
                    exit('error');
                }
            } else {
                echo '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>';
                exit('error');
            }
        } else {
            echo '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>';
            exit('error');
        }
    }


    //支付
    public function getPayUrl($order)
    {
        //配置
        $file = 'wxpay';
        $appid = config('wx.app_id');
        $mch_id = config('wx.mch_id');
        $user = UserModel::where('id', $order['user_id'])->find();
        $r = request();
        $domain = $r->scheme() . '://' . $r->server()['SERVER_NAME'];
        $apiParams = [
            'appid' => $appid,
            'mch_id' => $mch_id,
            'nonce_str' => Util::getNonceStr(31),
            'body' =>  $order['remark'],
            'out_trade_no' => $order['no'],
            'spbill_create_ip' => $_SERVER['SERVER_ADDR'],
            'total_fee' => $order['price'] * 100,
            'trade_type' => 'JSAPI',
            'notify_url' => $domain . "/api/wxpay/notify",
            'openid' => $user['openid']
        ];
        //验签
        $apiParams['sign'] = $this->getSign($apiParams);
        $xml = Util::arrToXml($apiParams);
        $result = Util::postXmlCurl($xml, 'https://api.mch.weixin.qq.com/pay/unifiedorder');
        $arr = Util::xmlToArr($result);
        if ($arr['return_code'] == 'SUCCESS' && $arr['result_code'] == 'SUCCESS') {
            $jsapi_params = [
                'appId' => $arr['appid'],
                'timeStamp' => time(),
                'nonceStr' => $arr['nonce_str'],
                'package' => 'prepay_id=' . $arr['prepay_id'],
                'signType' => 'MD5',
            ];
            $jsapi_params['paySign'] = $this->getSign($jsapi_params);
            return $jsapi_params;
        } else {
            BaseModel::log($file, $result);
            return false;
        }
    }

    //回收支付
    public function getRecyclePayUrl($order)
    {
        $no = RecycleOrderModel::getNewOrderId(1);
        $order->no = $no;
        $order->save();
        //配置
        $file = 'wxrecyclepay';
        $appid = config('wx.app_id');
        $mch_id = config('wx.mch_id');
//        $user = UserModel::where('id', $order['user_id'])->find();
        $category_name = RecycleOrderItemModel::categoryName($order->id);
        $riderUser = UserModel::getUser($order['role_id']);
        $apiParams = [
            'appid' => $appid,
            'mch_id' => $mch_id,
            'nonce_str' => Util::getNonceStr(31),
            'body' => $category_name,
            'out_trade_no' => $order['no'],
            'spbill_create_ip' => $_SERVER['SERVER_ADDR'],
            'total_fee' => $order['actual_price'] * 100,
            'trade_type' => 'JSAPI',
            'notify_url' => "http://" . $_SERVER['HTTP_HOST'] . "/api/wxpay/recycleNotify",
            'openid' => $riderUser['openid']
        ];
        //验签
        $apiParams['sign'] = $this->getSign($apiParams);
        $xml = Util::arrToXml($apiParams);
        $result = Util::postXmlCurl($xml, 'https://api.mch.weixin.qq.com/pay/unifiedorder');
        $arr = Util::xmlToArr($result);
        if ($arr['return_code'] == 'SUCCESS' && $arr['result_code'] == 'SUCCESS') {
            $jsapi_params = [
                'appId' => $arr['appid'],
                'timeStamp' => time(),
                'nonceStr' => $arr['nonce_str'],
                'package' => 'prepay_id=' . $arr['prepay_id'],
                'signType' => 'MD5',
            ];
            $jsapi_params['paySign'] = $this->getSign($jsapi_params);
            return $jsapi_params;
        } else {
            BaseModel::log($file, $result);
            return false;
        }
    }

    /**
     * 退款
     * @return bool|Json
     */
    public function refund($order)
    {
        $file = 'wx_refund';
        $apiparams = [
            'appid' => config('wx.app_id'),
            'mch_id' => config('wx.mch_id'),
            'nonce_str' => Util::getNonceStr(31),
            'out_refund_no' => $order['no'],
            'refund_fee' => $order['actual_price'] * 100,
            'total_fee' => $order['actual_price'] * 100,
            'transaction_id' => $order['payment_no'],
        ];
        $apiparams['sign'] = $this->getSign($apiparams);
        $xml = Util::arrToXml($apiparams);
        $result = Util::postXmlCurl($xml, 'https://api.mch.weixin.qq.com/secapi/pay/refund', true);
        BaseModel::log($file, $result);
        $arr = Util::xmlToArr($result);
        if (isset($arr['result_code']) && $arr['return_code'] == 'SUCCESS' && $arr['result_code'] == 'SUCCESS') {
            $refund_id = $arr['refund_id'];
            return $refund_id;
        } else {
            return false;
        }
    }

    //验签
    public function getSign($params)
    {
        ksort($params);
        $str = urldecode(http_build_query($params) . "&key=" . config('wx.key'));
        return strtoupper(md5($str));
    }
}